package PrjHttpWs

import (
	"errors"
	"fmt"
	"io/ioutil"
	"sync/atomic"
	"time"

	"golang.org/x/net/websocket"
)

type WsConnEx struct {
	sendingflag uint32 // 发送标记
	conn        *websocket.Conn
	lastRecvT   time.Time // 建立时间,或者最后接收数据时间
}

func NewWsConnEx(conn *websocket.Conn) *WsConnEx {
	rval := &WsConnEx{
		conn:      conn,
		lastRecvT: time.Now(),
	}
	return rval
}

func (this *WsConnEx) Close() {
	conn := this.conn
	if conn != nil {
		conn.Close()
	}
}

func (this *WsConnEx) ReceiveMessage() (msgtype byte, msg []byte, err error) {
again:
	conn := this.conn
	frame, err := conn.NewFrameReader()
	if err != nil {
		return 0, nil, err
	}
	this.lastRecvT = time.Now()
	frame, err = conn.HandleFrame(frame)
	if err != nil {
		return 0, nil, err
	}
	if frame == nil {
		goto again
	}
	maxPayloadBytes := conn.MaxPayloadBytes
	if maxPayloadBytes == 0 {
		maxPayloadBytes = websocket.DefaultMaxPayloadBytes
	}
	payloadType := frame.PayloadType()
	data, err := ioutil.ReadAll(frame)
	if err != nil {
		return 0, nil, err
	}
	return payloadType, data, err
}

func (this *WsConnEx) SendWsMessage(msgtype byte, msg []byte) error {
	if atomic.CompareAndSwapUint32(&this.sendingflag, 0, 1) {
		defer func() {
			this.sendingflag = 0
		}()
		conn := this.conn
		if conn == nil {
			return errors.New("尚未建立连接")
		}
		writer, err := conn.NewFrameWriter(msgtype)
		if err != nil {
			return err
		}
		_, err = writer.Write(msg)
		return err
	} else {
		return fmt.Errorf("发送失败,多线程重入!")
	}
}

func (this *WsConnEx) SendPingMessage() error {
	if atomic.CompareAndSwapUint32(&this.sendingflag, 0, 1) {
		defer func() {
			this.sendingflag = 0
		}()
		conn := this.conn
		if conn == nil {
			return errors.New("尚未建立连接")
		}
		writer, err := conn.NewFrameWriter(websocket.PingFrame)
		if err != nil {
			return err
		}
		_, err = writer.Write([]byte{})
		return err
	} else {
		return fmt.Errorf("发送失败,多线程重入!")
	}

}

func (this *WsConnEx) CheckTimeOut(timeout time.Duration) bool {
	return time.Now().Sub(this.lastRecvT) > timeout
}
